package com.ssl.basics.io;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 描述：多个线程同时操作同一个文件，会导致读取到的文件内容错误，需要加上读写锁
 *
 * @author ssl
 * @create 2021/7/14 0014.
 */
@Slf4j(topic = "com.ssl.thread")
public class BlockIODemo {

    public static void main(String[] args) throws InterruptedException {
/*        new Thread(() -> {
            log.info("{} 开始读取文件···", Thread.currentThread().getName());
            try {
                file[0] = FileUtils.readFileToByteArray(new File("D:\\idea\\ideaIU-2020.3.3.exe"));

                FileUtils.writeByteArrayToFile(new File("D:\\idea\\123.exe"), file[0]);
                log.info("{} 读取到文件大小：{}",Thread.currentThread().getName(),file[0].length);
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("{} 读取文件成功···", Thread.currentThread().getName());
        }, "t1").start();

        new Thread(() -> {
            try {
                file[0] = FileUtils.readFileToByteArray(new File("D:\\idea\\ideaIU-2020.3.3.exe"));
                FileUtils.writeByteArrayToFile(new File("D:\\idea\\123.exe"), file[0]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("{} 读取到文件大小：{}",Thread.currentThread().getName(),file[0].length);
        }, "t2").start();

        log.info("{} 执行结束", Thread.currentThread().getName());*/
        long start = System.currentTimeMillis();
        int threadSize = 100;
        CountDownLatch latch = new CountDownLatch(threadSize);


        ReadWriteLock rwLock = new ReentrantReadWriteLock();
        Lock rLock = rwLock.readLock();
        Lock wLock = rwLock.writeLock();
        for (int i = 0; i < threadSize; i++) {
            new Thread(() -> {
                try {
                    // 必须要加上读写锁，否则会导致读取的错误的文件内容
                    //rLock.lock();
                    byte[] file = FileUtils.readFileToByteArray(new File("E:\\test\\pdf\\sy-result.pdf"));
                    //rLock.unlock();

                   // wLock.lock();
                    FileUtils.writeByteArrayToFile(new File("E:\\test\\pdf\\sy-result.pdf"), file);
                   // wLock.unlock();
                    log.info("{} 读取到文件大小：{}", Thread.currentThread().getName(), file.length);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            }, String.valueOf(i)).start();
        }
        latch.await();
        System.out.println((System.currentTimeMillis() - start));
    }
}
